#include <iostream>
#include <sys/socket.h> // 必选！socket(), bind(), listen(), accept() 等
#include <netinet/in.h> // 必选！struct sockaddr_in（IPv4 地址结构）
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h> // 必选！socket(), bind(), listen(), accept() 等
#include <string.h>
#include <stdlib.h>
#include <error.h>
#include <stdio.h>
#include <pthread.h>
#include "protecol.h"
#include <map>
#include <list>
#include "user.h"

// 常用！inet_addr(), inet_ntop()（IP 地址转换）
using namespace std;
map<int, int> user;
list<User> user_data;

void initUserDate()
{
    user_data = {
        {1, "user1", "123456", ":/image/image/1.jpg"},
        {2, "user2", "123456", ":/image/image/2.jpg"},
        {3, "user3", "123456", ":/image/image/3.jpg"}};
    cout << "初始化用户数据" << user_data.size() << endl;
}

void *threadFunc(void *arg)
{

    char body[1024] = {0};
    HEAD head = {0};
    int clientfd = *(int *)arg;
    while (1)
    {
        char send_buffer[1024] = {0};
        char recv_buffer[1024] = {0};
        int size = read(clientfd, &head, sizeof(HEAD));
        size = read(clientfd, body, head.data_len);
        if (size == 0)
        {
            break;
        }
        cout<<"head.service_type ="<<head.service_type<<endl;
        if (head.service_type == LOGIN)
        {
            LOGIN_REQ login_req = {0};
            memcpy(&login_req, body, head.data_len);
            cout << "id:" << login_req.id << ",password:" << login_req.password << endl;

            // 校验用户名和密码
            bool is_login = false;
            for (auto &e : user_data)
            {
                if (e.getId() == login_req.id && strcmp(e.getPasswd(), login_req.password) == 0)
                {
                    is_login = true;
                    break;
                }
            }
            LOGIN_RESP login_resp = {0};
            login_resp.id = login_req.id;
            if (is_login)
            {
                user[login_req.id] = clientfd; // 记录该用户上线
                //  响应数据到客户端
                login_resp.status = 0;
            }
            else if (!is_login)
            {
                // 登录未成功，返回对应的响应
                login_resp.status = 1;
            }
            bzero(&head, sizeof(HEAD));
            bzero(send_buffer,sizeof(send_buffer));

            head.service_type = LOGIN;
            head.data_len = sizeof(login_resp);

            memcpy(send_buffer, &head, sizeof(HEAD));
            memcpy(send_buffer + sizeof(HEAD), &login_resp, head.data_len);
            int len=write(clientfd, send_buffer, sizeof(HEAD) + head.data_len);
            cout<<"write len="<<len;
        }
        else if (head.service_type == CHAT)
        {
            CHAT_REQ chat_req = {0};
            CHAT_RESP chat_resp = {0};
            memcpy(&chat_req, body, head.data_len);
            if (user.count(chat_req.recv_id) == 0)
            {
                chat_resp.status = 0;
                strcpy(chat_resp.msg, "用户不在线");
                // 发送给客户端
                bzero(&head, sizeof(head));
                head.service_type = CHATRESP;
                head.data_len = sizeof(chat_resp);
                bzero(send_buffer, sizeof(send_buffer));
                memcpy(send_buffer, &head, sizeof(HEAD));
                memcpy(send_buffer + sizeof(HEAD), &chat_resp, head.data_len);
                write(user[chat_req.send_id], send_buffer, sizeof(HEAD) + sizeof(chat_resp));
            }
            else // 发送给对应的客户端
            {

                chat_resp.status = 1;
                strcpy(chat_resp.msg, "发送成功");
                bzero(&head, sizeof(head));
                head.service_type = CHATRESP;
                head.data_len = sizeof(chat_resp);
                bzero(send_buffer, sizeof(send_buffer));

                memcpy(send_buffer, &head, sizeof(HEAD));
                memcpy(send_buffer + sizeof(HEAD), &chat_resp, head.data_len);
                write(user[chat_req.send_id], send_buffer, sizeof(HEAD) + sizeof(chat_resp));

                // 直接发送数据过去
                head.service_type = CHATREQ;
                memcpy(&chat_req, body, head.data_len);
                memcpy(send_buffer, &head, sizeof(HEAD));
                memcpy(send_buffer + sizeof(HEAD), &chat_req, head.data_len);
                write(user[chat_req.recv_id], send_buffer, sizeof(HEAD) + sizeof(CHAT_REQ));
            }
        }
        else if (head.service_type == FRIEND)
        {
            FRI_RESP fri_resp;
            FRI_REQ fri_req = {0};
            memcpy(&fri_req, body, head.data_len);
            cout << "user_id:" << fri_req.id << endl;
            fri_resp.num = 0;
            int i = 0;
            for (auto e : user_data)
            {
                if (e.getId() != fri_req.id)
                {
                    fri_resp.users[fri_resp.num].id = e.getId();
                    strcpy(fri_resp.users[fri_resp.num].name, e.getName());
                    strcpy(fri_resp.users[fri_resp.num].icon, e.getIcon());
                    fri_resp.num++;
                }
            }
            cout<<"num="<<fri_resp.num<<endl;
            bzero(&head, sizeof(HEAD));
            bzero(send_buffer, sizeof(send_buffer));

            head.service_type = FRIEND;
            head.data_len = sizeof(fri_resp);

            memcpy(send_buffer, &head, sizeof(HEAD));
            memcpy(send_buffer + sizeof(HEAD), &fri_resp, head.data_len);
            cout<<"sizeof(HEAD) + head.data_len "<< head.data_len<<endl;
            int len=write(clientfd, send_buffer, sizeof(HEAD) + head.data_len);
            cout<<"fri write len="<<len<<endl;
            cout<<"fri type="<<head.service_type<<endl;
        }
    }
}

int main()
{
    initUserDate();
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    // 端口复用
    int opt = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); // 只需这一行！
    if (sockfd < 0)
    {
        perror("socket error");
        return 0;
    }
    // 绑定
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr("192.168.139.128");
    addr.sin_port = htons(8888);

    bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));

    struct sockaddr_in clientaddr;
    socklen_t clientlen = sizeof(clientaddr);
    listen(sockfd, 128);
    // 监听
    int pid = 0;
    while (1)
    {
        // 连接
        int clientfd = accept(sockfd, (struct sockaddr *)&clientaddr, &clientlen);
        if (clientfd == -1)
        {
            perror("accept error");
        }
#if 0
        //创建一个进程的方式
        pid = fork();
        if (pid == 0)
        {
            while (1)
            {
                char buffer[1024] = {0};
                int size = read(clientfd, buffer, sizeof(buffer));
                if (size == 0)
                {
                    break;
                }
                cout << "客户端发来数据 is " << buffer << endl;
                write(clientfd, buffer, size);
            }   
        }
#else
        // 创建一个进程的方式
        pthread_t thread_id;
        pthread_create(&thread_id, NULL, threadFunc, &clientfd);
#endif
    }

    close(sockfd);
    return 0;
}